package cn.com.yang.file;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * 
 * TODO
 * @author yangyijin
 * @since 2024年5月20日-下午2:42:40
 */
public class MultiThreadFileCopier {

	private static final int THREAD_COUNT = 6; // 线程数量

	public static void main(String[] args) {
		String sourceFilePath = "F:\\使用文档\\doc文件\\面试题准备.docx"; // 源文件路径
		String targetFilePath = "F:\\使用文档\\doc文件\\面试题准备_copy.docx"; // 目标文件路径

		File sourceFile = new File(sourceFilePath);
		File targetFile = new File(targetFilePath);

		long fileSize = sourceFile.length();
		long partSize = fileSize / THREAD_COUNT;

		ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
		// 创建线程并启动它们
		for (int i = 0; i < THREAD_COUNT; i++) {
			long start = i * partSize;
			long end = (i == THREAD_COUNT - 1) ? fileSize - 1 : start + partSize - 1;
			executorService.submit(new FileCopyThread(sourceFile, targetFile, start, end));
		}
		executorService.shutdown();
		// 注意：这里我们没有等待所有线程完成，因为Java的线程是并发执行的。
		// 如果你需要等待所有线程完成，你可以使用如CountDownLatch等同步机制。
		
	}

	// 这是一个内部类，用于表示执行文件复制任务的线程
	static class FileCopyThread extends Thread {
		private File sourceFile;
		private File targetFile;
		private long start;
		private long end;

		public FileCopyThread(File sourceFile, File targetFile, long start, long end) {
			this.sourceFile = sourceFile;
			this.targetFile = targetFile;
			this.start = start;
			this.end = end;
		}

		@Override
		public void run() {
			try (RandomAccessFile rafSource = new RandomAccessFile(sourceFile, "r");
					RandomAccessFile rafTarget = new RandomAccessFile(targetFile, "rw")) {

				rafTarget.seek(start); // 将目标文件的指针移动到开始位置

				byte[] buffer = new byte[1024]; // 缓冲区大小可以根据需要调整
				int bytesRead;
				rafSource.seek(start); // 将源文件的指针移动到开始位置
				while ((bytesRead = rafSource.read(buffer, 0, (int) Math.min(buffer.length, end - start + 1))) != -1) {
					if (start + bytesRead - 1 > end) {
						buffer = Arrays.copyOfRange(buffer, 0, (int) (end - start + 1));
					}
					rafTarget.write(buffer);
					start += bytesRead;
					if (start > end) {
						break;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
